/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
// -*- coding:iso-8859-15 mode: c++ -*-
/** 
 * \file
 * \brief MaCI_Wireless Logger implementation.
 * \author Matthieu Myrsky <matthieu.myrsky@tkk.fi>
 * \author Antti Maula <antti.maula@tkk.fi>
 *
 * $Id: WirelessLogger.cpp,v 1.4 2009-06-16 08:55:59 amaula Exp $
 *
 */
#include "WirelessLogger.hpp"
#include "gimutils.h"
#include "MaCICtrlClient.hpp"

//*****************************************************************************
//*****************************************************************************

WirelessLogger::WirelessLogger(MaCI::Wireless::CWirelessClient *aClient,
                               std::string aMaCISLName)
  : CSync(1, 1),               
    CThread(1),                
    Logger(),
    iClient(aClient),
    iRunning(false),
    iRunningThreadStopped(true),
    iFile(NULL),
    iMaCISLName(aMaCISLName),
    iMenu(),
    iTotalEvents(0)
{

  iMenu[std::string("Timestamp")] = true;
  iMenu[std::string("NodeSignal")] = true;
  iMenu[std::string("NodeRange")] = true;
  iMenu[std::string("NodePosition")] = true;
  iMenu[std::string("NodeID")] = true;
  /*
  iMenu = new wxMenu();
  wxMenuItem *title = iMenu->Insert(0,0,"LOG TYPES - (Check all for playing with MaCI_Player)");

  wxMenuItem *a = iMenu->InsertCheckItem(1,1,"Timestamp");
  a->Check(true);

  wxMenuItem *b = iMenu->InsertCheckItem(2,2,"NodeSignal");
  b->Check(true);

  wxMenuItem *c = iMenu->InsertCheckItem(3,3,"NodeRange");
  c->Check(true);

  wxMenuItem *d = iMenu->InsertCheckItem(4,4,"NodePosition");
  d->Check(true);

  wxMenuItem *e = iMenu->InsertCheckItem(5,5,"NodeID");
  e->Check(true);*/
}
//*****************************************************************************

WirelessLogger::~WirelessLogger()
{
  if(iRunning){
    StopLogging();
  }
 
}
//*****************************************************************************
 
bool WirelessLogger::StartLogging(void)
{
  dPrint(10,"Start called");
  
  if(!iRunning){

    char buffer[256];
    dPrint(5,"Start logging Wireless events");
    if(iFilenameSet){
  
      sprintf(buffer,"data/%s.txt",
             iFilename.c_str());
      
    }else{
    
      gim::time tstamp(true);
      tm t;
      //      MaCI::Common::TTimestamp tstamp;
      tstamp.getLocalTime(t);
       
      sprintf(buffer,"data/%s_%.2d_%.2d_%d_%.2d:%.2d:%.2d.txt",
              iMaCISLName.c_str(),
              t.tm_mday,
              t.tm_mon+1,
              t.tm_year+1900,
              t.tm_hour,
              t.tm_min,
              t.tm_sec);
              
     
    }
    
    iFile = fopen(buffer,"wt");
    /*    for(int i = 0; i < iMenu->GetMenuItemCount();i++){
      iMenu->Enable(i,false);
      }*/
    iRunning = true; 
    RunThread(0);
  }

  return false;
}
//*****************************************************************************
 
bool WirelessLogger::StopLogging(void)
{

  dPrint(10,"stop called");
  if(iRunning){
    Lock();
    iRunning = false;
    Unlock();
    WaitThread(0);
    /*
    for(int i = 0; i < iMenu->GetMenuItemCount();i++) {
      iMenu->Enable(i,true);
      }*/
    
    fclose(iFile);
  }
  return false;
}
//*****************************************************************************

int WirelessLogger::ThreadFunction(const int aThreadNumber)
{

  using namespace MaCI::Wireless;
  dPrint(1,"thread %d", aThreadNumber);
  if(aThreadNumber == 0){
    dPrint(1,"thread running");
    CWirelessData data;
    
    // Check types.
 

 
 

    const bool logTimestamp = iMenu[std::string("Timestamp")];
    const bool logSignal =   iMenu[std::string("NodeSignal")];
    const bool logRange =  iMenu[std::string("NodeRange")];
    const bool logPosition =  iMenu[std::string("NodePosition")];
    const bool logID =  iMenu[std::string("NodeID")];
    
    /////////Search the group and instance names :)
    std::string instance;
    std::string group;

    MaCI::MaCICtrl::SMaCISL sl(iMaCISLName);
    if (sl.IsValidFQMaCISL()) {
      group = sl.GetDeviceGroup();
      instance = sl.GetInstance();
    }
    //////////

    if (!group.size() || !instance.size()) {
      dPrint(ODERROR,"Failed to get MaCISL names for service, fatal error!");
      iRunningThreadStopped = true;
      return -1;
    }
    
    fprintf(iFile,"%%MaCI_Wireless log file v.2.0\n");
    fprintf(iFile,"%%Group: %s Instance: %s\n",group.c_str(),instance.c_str());

    fprintf(iFile,"%%");
    fprintf(iFile,"measurementIndex ");
    if(logTimestamp){
      fprintf(iFile,"timestamp_sec timestamp_usec ");

    }
    
    fprintf(iFile,"channel ");
    if(logSignal){
      fprintf(iFile,"signal_count [nodeid signal_level] ... ");

    }
    if(logRange){
      fprintf(iFile,"range_count [nodeid range variance] ... ");

    }
    if(logPosition){
      fprintf(iFile,"position_count [nodeid pos_x pos_y pos_z] ... ");

    }
    if(logID){
      fprintf(iFile,"id_count [nodeid ESSID] ... ");

    }
    fprintf(iFile,"\n\n");

    while(iRunning){
      if(iClient->WaitWirelessEvent(data,
                                    2000)){
        Lock();
        // Increment total events
        ++iTotalEvents;

        const TMeasurementIndex *measurementIndex = data.GetMeasurementIndex();
        if(measurementIndex){
          fprintf(iFile,"%u ",measurementIndex->measurementIndex);
        }else{
          fprintf(iFile,"0 ");
        }

        if(logTimestamp){
          const MaCI::Common::TTimestamp *tstamp = data.GetTimestamp();
          if(tstamp){
            fprintf(iFile,"%u %u ",tstamp->timestamp_s,tstamp->timestamp_us);
          }else{
            fprintf(iFile,"0 0 ");
          }
        }
        const TWirelessChannel *channel = data.GetWirelessChannel();
        if(channel){
          fprintf(iFile,"%u ",channel->channel);
        
        }else{
          fprintf(iFile,"0 ");
        }

        if(logSignal){
          const TNodeSignalPtrArray &signalarray = data.GetNodeSignalArray();
          //          dPrint(ODTEST,"%u entries in NodeSignalPtrArray", signalarray.size());
          fprintf(iFile,"%u ", signalarray.size());
          for(EACH_IN_i(signalarray)) {
            const TNodeSignal *sig = *i;
            fprintf(iFile,"0x%llx %d ", sig->nodeid, sig->signal_level);
          }
        }

        if(logRange){
          const TNodeRangePtrArray &rangearray = data.GetNodeRangeArray();
          //          dPrint(ODTEST,"%u entries in NodeRangePtrArray", rangearray.size());
          fprintf(iFile,"%u ", rangearray.size());
          for(EACH_IN_i(rangearray)) {
            const TNodeRange *range = *i;
            fprintf(iFile,"0x%llx %f %f ", range->nodeid, range->range, range->variance);
          }
        }
        
        if(logPosition){
          const TNodePositionPtrArray &positionarray = data.GetNodePositionArray();
          //          dPrint(ODTEST,"%u entries in NodePositionArray", positionarray.size());
          fprintf(iFile,"%u ", positionarray.size());
          for(EACH_IN_i(positionarray)) {
            const TNodePosition *pos = *i;
            fprintf(iFile,"0x%llx %f %f %f ", pos->nodeid, pos->pos_x, pos->pos_y, pos->pos_z);
          }
        }
        
        if(logID){
          const TNodeIDPtrArray &idarray = data.GetNodeIDArray();
          //          dPrint(ODTEST,"%u entries in NodeIDArray", idarray.size());
          fprintf(iFile,"%u ", idarray.size());
          for(EACH_IN_i(idarray)) {
            const TNodeID *id = *i;
            fprintf(iFile,"0x%llx '%s' ", id->nodeid, id->ESSID);
          }
        }

        fprintf(iFile,"\n");
        fflush(iFile);
        Unlock();
      }
    }
    // At-most-once access, no mutex required.
    iRunningThreadStopped = true;
    
  }

  return 0;

}
//*****************************************************************************

std::string WirelessLogger::GetName()
{
  return "Wireless Logger";
}
//*****************************************************************************

Logger::TMenu *WirelessLogger::GetMenu(void)
{
  return &iMenu;
}
//*****************************************************************************

bool WirelessLogger::GetAdditionalInformation(std::string &aInformation)
{
  char info[512];
  Lock();
  sprintf(info,"Total of %u Wireless events logged", iTotalEvents);
  Unlock();
  aInformation = info;

  return true;
}
//*****************************************************************************

bool WirelessLogger::SetMenuItem(std::string aItem, bool aValue){ 


  if(!iRunning){
    iMenu[aItem] =  aValue;
    return true;
  }else{
    return false;
  }

}
//*****************************************************************************
